﻿using System;
using System.Diagnostics;
using SHDocVw;

namespace SpicIE.Parameter
{
    /// <summary>
    /// Class containing all adopted properties for the IWebBrowser2 control
    /// </summary>
    [CLSCompliant(false)]
    public class Browser
    {
        protected static IWebBrowser2 browserRef;

        /// <summary>
        /// Global browser constructor
        /// </summary>
        /// <param name="browser"></param>
        public Browser(IWebBrowser2 browser)
        {
            browserRef = browser;
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the address bar of the object is visible or hidden.
        /// </summary>
        public bool AddressBar
        {
            get
            {
                return (browserRef != null) ? browserRef.AddressBar : false;
            }
            set
            {
                browserRef.AddressBar = value;
            }
        }

        /// <summary>
        /// Gets a value that indicates whether the object is engaged in a navigation or downloading operation.
        /// </summary>
        public bool IsBusy
        {
            get
            {
                return (browserRef != null) ? browserRef.Busy : false;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether Windows Internet Explorer is in full-screen mode or normal window mode.
        /// </summary>
        public bool FullScreen
        {
            get
            {
                return (browserRef != null) ? browserRef.FullScreen : false;
            }
            set
            {
                browserRef.FullScreen = value;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the object is visible or hidden.
        /// </summary>
        public bool Visible
        {
            get
            {
                return (browserRef != null) ? browserRef.Visible : false;
            }
            set
            {
                browserRef.Visible = value;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the object can be resized.
        /// </summary>
        public bool Resizable
        {
            get
            {
                return (browserRef != null) ? browserRef.Resizable : false;
            }
            set
            {
                browserRef.Resizable = value;
            }
        }

        /// <summary>
        /// Sets or gets whether the object is in theater mode. 
        /// </summary>
        public bool TheaterMode
        {
            get
            {
                return (browserRef != null) ? browserRef.TheaterMode : false;
            }
            set
            {
                browserRef.TheaterMode = value;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the object is registered as a top-level browser window.
        /// </summary>
        public bool RegisterAsBrowser
        {
            get
            {
                return (browserRef != null) ? browserRef.RegisterAsBrowser : false;
            }
            set
            {
                browserRef.RegisterAsBrowser = value;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the Windows Internet Explorer menu bar is visible.
        /// </summary>
        public bool MenuBar
        {
            get
            {
                return (browserRef != null) ? browserRef.MenuBar : false;
            }
            set
            {
                browserRef.MenuBar = value;
            }
        }

        /// <summary>
        /// Sets or gets whether toolbars for the object are visible.
        /// </summary>
        public int ToolBar
        {
            get
            {
                return (browserRef != null) ? browserRef.ToolBar : 0;
            }
            set
            {
                browserRef.ToolBar = value;
            }
        }


        /// <summary>
        /// Sets or gets a value that indicates whether the object is operating in offline mode. 
        /// </summary>
        public bool Offline
        {
            get
            {
                return (browserRef != null) ? browserRef.Offline : false;
            }
            set
            {
                browserRef.Offline = value;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the object can display dialog boxes.
        /// </summary>
        public bool Silent
        {
            get
            {
                return (browserRef != null) ? browserRef.Silent : false;
            }
            set
            {
                browserRef.Silent = value;
            }
        }

        /// <summary>
        /// Sets or gets a value that indicates whether the status bar for the object is visible.
        /// </summary>
        public bool StatusBar
        {
            get
            {
                return (browserRef != null) ? browserRef.StatusBar : false;
            }
            set
            {
                browserRef.StatusBar = value;
            }
        }

        /// <summary>
        /// Sets or gets the height of the object.
        /// </summary>
        public int Height
        {
            get
            {
                return (browserRef != null) ? browserRef.Height : 600;
            }
            set
            {
                browserRef.Height = value;
            }
        }

        /// <summary>
        /// Sets or gets the width of the object.
        /// </summary>
        public int Width
        {
            get
            {
                return (browserRef != null) ? browserRef.Width : 800;
            }
            set
            {
                browserRef.Width = value;
            }
        }

        /// <summary>
        /// Sets or gets the coordinate of the left edge of the object.
        /// </summary>
        public int Left
        {
            get
            {
                return (browserRef != null) ? browserRef.Left : 800;
            }
            set
            {
                browserRef.Left = value;
            }
        }

        /// <summary>
        /// Sets or gets the coordinate of the top edge of the object.
        /// </summary>
        public int Top
        {
            get
            {
                return (browserRef != null) ? browserRef.Top : 800;
            }
            set
            {
                browserRef.Top = value;
            }
        }

        /// <summary>
        /// Gets the parent of the object.
        /// </summary>
        public object Parent
        {
            get
            {
                return (browserRef != null) ? browserRef.Parent : null;
            }
        }

        /// <summary>
        /// Gets the automation object of the active document, if any.
        /// </summary>
        public Document CurrentDocument
        {
            get
            {
                return (browserRef != null) ? new Document(browserRef.Document) : null;
            }
        }

        /// <summary>
        /// Retrieves the system folder of the Windows Internet Explorer executable.
        /// </summary>
        public string Path
        {
            get
            {
                return (browserRef != null) ? browserRef.Path : string.Empty;
            }
        }

        /// <summary>
        /// Sets or gets the text in the status bar for the object.
        /// </summary>
        public string StatusText
        {
            get
            {
                return (browserRef != null) ? browserRef.StatusText : string.Empty;
            }
            set
            {
                browserRef.StatusText = value;
            }
        }

        /// <summary>
        /// Retrieves the path or title of the resource that is currently displayed.
        /// </summary>
        public string LocationName
        {
            get
            {
                return (browserRef != null) ? browserRef.LocationName : string.Empty;
            }
        }

        /// <summary>
        /// Gets the URL of the resource that is currently displayed.
        /// </summary>
        public string LocationURL
        {
            get
            {
                return (browserRef != null) ? browserRef.LocationURL : string.Empty;
            }
        }

        /// <summary>
        /// Retrieves the frame name or application name of the object.
        /// </summary>
        public string Name
        {
            get
            {
                return (browserRef != null) ? browserRef.Name : string.Empty;
            }
        }

        /// <summary>
        /// Gets the ready state of the object.
        /// </summary>
        public State ReadyState
        {
            get
            {
                if (browserRef != null)
                {
                    string[] state = browserRef.ReadyState.ToString().Split('_');
                    return (State)Enum.Parse(typeof(State), state[1].ToLower());
                }
                else
                {
                    return State.uninitialized;
                }
            }

        }

        /// <summary>
        /// Shows or hides a specified browser bar.
        /// </summary>
        /// <param name="target">A enumeration of currently available browserbars, choose CLSID to use a custom bar</param>
        /// <param name="clsid">Specify the CLSID for your sutom browserbar</param>
        /// <param name="isVisible">Set the value to true if the bar should be visible</param>
        public void ShowBrowserBar(BrowserBar target, string clsid, bool isVisible)
        {
            try
            {
                object value;
                if (target == BrowserBar.clsid)
                    value = clsid;
                else
                    value = target;

                object show = isVisible;
                object size = 0;
                browserRef.ShowBrowserBar(ref value, ref show, ref size);
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.ShowBrowserBar, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Reloads the file that is currently displayed in the object.
        /// </summary>
        public void Refresh()
        {
            try
            {
                browserRef.Refresh();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Refresh, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Reloads the file that is currently displayed with the specified refresh level.
        /// </summary>
        /// <param name="refreshType">specifies the type of refresh level</param>
        public void Refresh2(RefreshConstants refreshType)
        {
            object oType = refreshType;
            try
            {
                browserRef.Refresh2(ref oType);
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Refresh2, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Navigates to a resource identified by a URL or to a file identified by a full path.
        /// </summary>
        /// <param name="url">A BSTR expression that evaluates to the URL, full path, or Universal Naming Convention (UNC) location and name of the resource to display.</param>
        /// <param name="flags">A combination of the values defined by the BrowserNavConstants enumeration.</param>
        /// <param name="target">A case-sensitive string that contains the name of the frame in which to display the resource.</param>
        /// <param name="postdata">An array of byte that is sent to the server as part of a HTTP POST transaction. A POST transaction is typically used to send data gathered by an HTML form. If this parameter does not specify any post data, this method issues an HTTP GET transaction. </param>
        /// <param name="headers">A string that contains additional HTTP headers to send to the server.</param>
        public void Navigate(string url, BrowserNavConstants[] flags, TargetFrameName target, byte[] postdata, string[] headers)
        {
            try
            {
                Int32 flagCollection = 0;
                foreach (Int32 flag in flags)
                {
                    flagCollection += flag;
                }
                object oFlags = flagCollection;
                object oTarget = target;
                object oPostdata = postdata;
                object oHeaders = headers;

                browserRef.Navigate(url, ref oFlags, ref oTarget, ref oPostdata, ref oHeaders);
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Navigate, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Navigates the browser to a location that might not be expressed as a URL, such as a pointer to an item identifier list (PIDL) for an entity in the Microsoft Windows Shell namespace.
        /// </summary>
        /// <param name="url">An expression that evaluates to the URL of the resource to display, the full path to the file location, or a PIDL that represents a folder in the Shell namespace.</param>
        /// <param name="flags">A combination of the values defined by the BrowserNavConstants enumeration.</param>
        /// <param name="target">A case-sensitive string that contains the name of the frame in which to display the resource.</param>
        /// <param name="postdata">An array of byte that is sent to the server as part of a HTTP POST transaction. A POST transaction is typically used to send data gathered by an HTML form. If this parameter does not specify any post data, this method issues an HTTP GET transaction. </param>
        /// <param name="headers">A string that contains additional HTTP headers to send to the server.</param>
        public void Navigate2(string url, BrowserNavConstants[] flags, TargetFrameName target, byte[] postdata, string[] headers)
        {
            try
            {
                Int32 flagCollection = 0;
                foreach (Int32 flag in flags)
                {
                    flagCollection += flag;
                }
                object oUrl = url;
                object oFlags = flagCollection;
                object oTarget = target;
                object oPostdata = postdata;
                object oHeaders = headers;

                browserRef.Navigate2(ref oUrl, ref oFlags, ref oTarget, ref oPostdata, ref oHeaders);
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Navigate2, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Computes the full size of the browser window when given the specified width and height of the content area.
        /// </summary>
        /// <param name="width">new width of the object</param>
        /// <param name="height">new height of the object</param>
        public void Client2Window(int width, int height)
        {
            try
            {
                browserRef.ClientToWindow(ref width, ref height);
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Client2Window, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Cancels a pending navigation or download, and stops dynamic page elements, such as background sounds and animations.
        /// </summary>
        public void Stop()
        {
            try
            {
                browserRef.Stop();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Stop, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Closes the object. 
        /// </summary>
        public void Quit()
        {
            try
            {
                browserRef.Quit();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.Quit, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Navigates backward one item in the history list.
        /// </summary>
        public void GoBack()
        {
            try
            {
                browserRef.GoBack();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.GoBack, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Navigates forward one item in the history list.
        /// </summary>
        public void GoForward()
        {
            try
            {
                browserRef.GoForward();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.GoForward, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Navigates to the current home or start page.
        /// </summary>
        public void GoHome()
        {
            try
            {
                browserRef.GoHome();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.GoHome, error in invoke: " + ex);
            }
        }

        /// <summary>
        /// Navigates to the current search page.
        /// </summary>
        public void GoSearch()
        {
            try
            {
                browserRef.GoSearch();
            }
            catch (Exception ex)
            {
                SpicIE.Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Parameter_Browser.GoSearch, error in invoke: " + ex);
            }
        }

        #region Browser enums
        public enum BrowserBar
        {
            clsid = 0x0000,
            addressbar = 0x0009,
            toolbar = 0x000a,
            linkbar = 0x000b
        } ;

        public enum RefreshConstants
        {
            REFRESH_NORMAL = 0,
            REFRESH_IFEXPIRED = 1,
            REFRESH_COMPLETELY = 3
        } ;

        public enum State
        {
            complete,
            interactive,
            loaded,
            loading,
            uninitialized
        } ;

        public enum TargetFrameName
        {
            _blank,
            _parent,
            _self,
            _top
        } ;

        public enum BrowserNavConstants
        {
            navOpenInNewWindow = 0x1,
            navNoHistory = 0x2,
            navNoReadFromCache = 0x4,
            navNoWriteToCache = 0x8,
            navAllowAutosearch = 0x10,
            navBrowserBar = 0x20,
            navHyperlink = 0x40,
            navEnforceRestricted = 0x80,
            navNewWindowsManaged = 0x0100,
            navUntrustedForDownload = 0x0200,
            navTrustedForActiveX = 0x0400,
            navOpenInNewTab = 0x0800,
            navOpenInBackgroundTab = 0x1000,
            navKeepWordWheelText = 0x2000
        };
        #endregion
    }
}
